//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
/*
 * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Thomas Roell not be used in
 * advertising or publicity pertaining to distribution of the software without
 * specific, written prior permission.  Thomas Roell makes no representations
 * about the suitability of this software for any purpose.  It is provided
 * "as is" without express or implied warranty.
 *
 * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 * Author:  Thomas Roell, roell@informatik.tu-muenchen.de
 *
 */
#include <ddk.h>
#include "X.h"
#include "Xmd.h"
#include "compiler.h"
#include "xf86.h"
#include "xf86Priv.h"
#include "xf86Procs.h"
#include "xf86_OSlib.h"
#include "xf86_Config.h"
#include "gdivga.h"
#include "xf86_pci.h"
#include "vgamisc.h"

unsigned long useSpeedUp = 0;
extern void speedupvga256TEGlyphBlt8();
extern void speedupvga2568FillRectOpaqueStippled32();
extern void speedupvga2568FillRectTransparentStippled32();
extern void OneBankvgaBitBlt();
extern Boolean miDCInitialize();
extern char *xf86VisualNames[];

extern Boolean xf86Exiting, xf86Resetting, xf86ProbeFailed;

int vgaValidMode(DisplayModePtr mode,Boolean verbose,int flag);
void vgaEnterLeaveVT(Boolean enter,int screen_idx);
void vgaAdjustFrame(int x, int  y);
void vgaPrintIdent();
Boolean vgaSwitchMode(DisplayModePtr mode);
Boolean vgaProbe();
Boolean vgaScreenInit(int scr_index,ScreenPtr pScreen, int argc,char **argv);

int vga256ValidTokens[] =
{
    STATICGRAY,
    GRAYSCALE,
    STATICCOLOR,
    PSEUDOCOLOR,
    TRUECOLOR,
    DIRECTCOLOR,
    CHIPSET,
    CLOCKS,
    MODES,
    OPTION,
    VIDEORAM,
    VIEWPORT,
    VIRTUAL,
    CLOCKPROG,
    BIOSBASE,
    MEMBASE,
    RAMDAC,
    DACSPEED,
    -1
};
int xf86ScreenNames[] =
{
    SVGA,
    -1
};

ScrnInfoRec SvgaInfoRec = {
    FALSE,                    /* Boolean configured */
    -1,                       /* int tmpIndex */
    -1,                       /* int scrnIndex */
    vgaProbe,                 /* Boolean (* Probe)() */
    vgaScreenInit,            /* Boolean (* Init)() */
    vgaValidMode,             /* Boolean (* ValidMode)() */
    vgaEnterLeaveVT,          /* void (* EnterLeaveVT)() */
    (void (*)())NoopDDA,      /* void (* EnterLeaveMonitor)() */
    (void (*)())NoopDDA,      /* void (* EnterLeaveCursor)() */
    vgaAdjustFrame,           /* void (* AdjustFrame)() */
    vgaSwitchMode,            /* Boolean (* SwitchMode)() */
    vgaDPMSSet,               /* void (* DPMSSet)() */
    vgaPrintIdent,            /* void (* PrintIdent)() */
#ifdef MONOVGA
    1,			/* int depth */
#else
#ifdef XF86VGA16
    4,			/* int depth */
#else
    8,			/* int depth */
#endif
#endif                      /* int depth */
    {5, 6, 5},                /* xrgb weight */
#ifdef MONOVGA
    1,			/* int bitsPerPixel */
#else
    8,			/* int bitsPerPixel */
#endif
    -1,                       /* int defaultVisual */
    -1, -1,                   /* int virtualX,virtualY */
    -1,                       /* int displayWidth */
    -1, -1, -1, -1,           /* int frameX0, frameY0, frameX1, frameY1 */
    {0, },                    /* OFlagSet options */
    {0, },                    /* OFlagSet clockOptions */
    {0, },                    /* OFlagSet xconfigFlag */
    NULL,                     /* char *chipset */
    NULL,                     /* char *ramdac */
    {0, 0, 0, 0},             /* int dacSpeeds[MAXDACSPEEDS] */
    0,                        /* int dacSpeedBpp */
    0,                        /* int clocks */
    {0, },                    /* int clock[MAXCLOCKS] */
    DEFAULT_MAX_CLOCK,        /* int maxClock */
    0,                        /* int videoRam */
    0xC0000,                  /* int BIOSbase */
    0,                        /* unsigned long MemBase,unused for this driver */
    240, 180,                 /* int width, height */
    0,                        /* unsigned long speedup */
    NULL,                     /* DisplayModePtr modes */
    NULL,                     /* MonPtr monitor */
    NULL,                     /* char *clockprog */
    -1,                       /* int textclock */
    FALSE,                    /* Boolean bankedMono */
#ifdef MONOVGA
    "VGA2",		/* char *name */
#else
#ifdef XF86VGA16
    "VGA16",		/* char *name */
#else
    "SVGA",		/* char *name */
#endif
#endif
    {0, 0, 0},                /* xrgb blackColour */
    {0x3F, 0x3F, 0x3F},       /* xrgb whiteColour */
    vga256ValidTokens,        /* int *validTokens */
    SVGA_PATCHLEVEL,          /* char *patchLevel */
    0,                        /* int IObase */
    0,                        /* int PALbase */
    0,                        /* int COPbase */
    0,                        /* int POSbase */
    0,                        /* int instance */
    0,                        /* int s3Madjust */
    0,                        /* int s3Nadjust */
    0,                        /* int s3MClk */
    0,                        /* int chipID */
    0,                        /* int chipRev */
    0x0A0000,                 /* unsigned long VGAbase */
    0,                        /* int s3RefClk */
    -1,                       /* int s3BlankDelay */
    0,                        /* int textClockFreq */
    NULL,                     /* char* DCConfig */
    NULL,                     /* char* DCOptions */
    0                         /* int MemClk */
};

extern vgaVideoChipRec SIS;
extern vgaVideoChipRec CHIPS;
extern vgaVideoChipRec CYRIX;
extern vgaVideoChipRec GENERIC;
extern vgaVideoChipRec I810;
extern vgaVideoChipRec S3V;
vgaVideoChipPtr Drivers[] = {&CHIPS, &CYRIX, &I810, &S3V, &SIS, &GENERIC, 0};

pointer vgaOrigVideoState = NULL;
pointer vgaNewVideoState  = NULL;
pointer vgaBase           = NULL;
pointer vgaVirtBase       = NULL;
pointer vgaLinearBase     = NULL;
pointer vgaLinearOrig     = NULL;
pciConfigPtr  *vgaPCIInfo = NULL;

extern void (* vgaSaveScreenFunc)(long int) ;
Boolean  (* vgaInitFunc)(DisplayModePtr)       = (Boolean (*)(DisplayModePtr))NoopDDA;
Boolean  (* vgaScrInitFunc)(ScreenPtr, char *, int, int, int, int, int) = \
        (Boolean (*)(ScreenPtr, char *, int, int, int, int, int))NoopDDA;
void  (* vgaEnterLeaveFunc)(Boolean) = (void (*)(Boolean))NoopDDA;
void  *(* vgaSaveFunc)(void *)       = (void *(*)(void *))NoopDDA;
void  (* vgaRestoreFunc)(void *)     = (void (*)(void *))NoopDDA;
void  (* vgaAdjustFunc)(int, int)      = (void (*)(int, int))NoopDDA;
void  (* vgaFbInitFunc)()      = (void (*)())NoopDDA;
void  (* vgaSetReadFunc)()     = (void (*)())NoopDDA;
void  (* vgaSetWriteFunc)()    = (void (*)())NoopDDA;
void  (* vgaSetReadWriteFunc)()= (void (*)())NoopDDA;
int   (* vgaValidModeFunc)(DisplayModePtr, Boolean, int)   = \
        (int (*)(DisplayModePtr, Boolean, int))NoopDDA;
int   (* vgaPitchAdjustFunc)() = (int (*)())NoopDDA;
int   (* vgaLinearOffsetFunc)()= (int (*)())NoopDDA;

int   vgaMapSize;
int   vgaSegmentSize;
int   vgaSegmentShift;
int   vgaSegmentMask;
int   vgaInterlaceType;
int   vgaPhysLinearBase;
int   vgaLinearSize;
int   vgaBytesPerPixel = 0;
void  *vgaReadBottom;
void  *vgaReadTop;
void  *vgaWriteBottom;
void  *vgaWriteTop =  NULL;//(pointer)&writeseg; /* dummy for linking */
Boolean  vgaReadFlag;
Boolean  vgaWriteFlag;
Boolean  vgaUse2Banks;
Boolean  vgaUseLinearAddressing;
OFlagSet vgaOptionFlags;

int vgaBitsPerPixel = 8;
extern Boolean clgd6225Lcd;

Boolean DAC8Bit = FALSE;

static ScreenPtr savepScreen = NULL;
static Boolean (* saveInitFunc)(DisplayModePtr);
static void * (* saveSaveFunc)(void *);
static void (* saveRestoreFunc)(void *);
static void (* saveAdjustFunc)(int, int);
static void (* saveSaveScreenFunc)(long int);
static void (* saveSetReadFunc)();
static void (* saveSetWriteFunc)();
static void (* saveSetReadWriteFunc)();
static Boolean vgaCloseScreen(int, ScreenPtr);
static Boolean vgaCloseScreen(int , ScreenPtr);


int defaultColorVisualClass = -1;

/*
 * vgaPrintIdent --
 *     Prints out identifying strings for drivers included in the server
 */
void
vgaPrintIdent()
{
    int            i, j, n, c;
    char         *id;

#ifdef MONOVGA
  kprintf("  %s: server for monochrome VGA (Patchlevel %s):\n      ", \
         SvgaInfoRec.name, SvgaInfoRec.patchLevel);
#else
#ifdef XF86VGA16
  kprintf("  %s: server for 4-bit colour VGA (Patchlevel %s):\n      ", \
         SvgaInfoRec.name, SvgaInfoRec.patchLevel);
#else
  kprintf("  %s: server for SVGA graphics adaptors (Patchlevel %s):\n      ", \
         SvgaInfoRec.name, SvgaInfoRec.patchLevel);
#endif
#endif

    n = 0;
    c = 0;
    for (i=0; Drivers[i]; i++) {
        id = (Drivers[i]->ChipIdent)(0);
        for (j = 0; id; n++) {
            if (n) {
                kprintf(",");
                c++;
                if (c + 1 + strlen(id) < 70)
                {
                    kprintf(" ");
                    c++;
                }
                else {
                    kprintf("\n      ");
                    c = 0;
                }
            }
            kprintf("%s", id);
            c += strlen(id);
            j++;
            id = (Drivers[i]->ChipIdent)(j);
        }
    }
    kprintf("\n");
}

/*
 * vgaProbe --
 *     probe and initialize the hardware driver
 */
Boolean
vgaProbe()
{
    DisplayModePtr pMode, pEnd, pmaxX = NULL, pmaxY = NULL;
    int            maxX, maxY;
    int            needmem, rounding;
    int            tx,ty;
    int            i, j;
    Boolean           defaultVisualGiven = FALSE;

    /*
     * At this point xf86bpp is what's given as -bpp on the command
     * line, or what is specified as DefaultColorDepth in the XF86Config
     * file.  The true depth/bits-per-pixel are yet to be determined.
     * At this point, the weights are uninitialized unless specifically
     * given by the user. Here we determine good defaults if weights haven't
     * been explicitly given.
     */

    if(SvgaInfoRec.defaultVisual >= 0)
        defaultVisualGiven = TRUE;

    if (xf86bpp <= 0)
#ifdef MONOVGA
        xf86bpp = 1;
#else
#ifdef XF86VGA16
        xf86bpp = 4;
#else
        xf86bpp = 8;
#endif
#endif

    switch (xf86bpp) {
#ifdef MONOVGA
    case 1:
        SvgaInfoRec.depth = 1;
        SvgaInfoRec.bitsPerPixel = 1;
        if (!defaultVisualGiven)
            SvgaInfoRec.defaultVisual = StaticGray;
        xf86weight.red = 1;
        xf86weight.green = 1;
        xf86weight.blue = 1;
        break;
#else
#ifdef XF86VGA16
    case 4:
        SvgaInfoRec.depth = 4;
        SvgaInfoRec.bitsPerPixel = 8;	/* This is a special case though */
        if (!defaultVisualGiven)
            SvgaInfoRec.defaultVisual = StaticColor;
        xf86weight.red = 6;
        xf86weight.green = 6;
        xf86weight.blue = 6;
        break;
#else
    case 8:
        SvgaInfoRec.depth = 8;
        SvgaInfoRec.bitsPerPixel = 8;
        xf86weight.red = 6;
        xf86weight.green = 6;
        xf86weight.blue = 6;
        break;
    case 15:
        SvgaInfoRec.depth = 15;
        SvgaInfoRec.bitsPerPixel = 16;
        if (!defaultVisualGiven)
            SvgaInfoRec.defaultVisual = TrueColor;
        xf86weight.red = 5;
        xf86weight.green = 5;
        xf86weight.blue = 5;
        break;
    case 16:
        SvgaInfoRec.bitsPerPixel = 16;
        if (!defaultVisualGiven)
            SvgaInfoRec.defaultVisual = TrueColor;
#if 0
        if (xf86weight.red && xf86weight.green && xf86weight.blue) {
            SvgaInfoRec.depth = xf86weight.red + xf86weight.green +
                                  xf86weight.blue;
            if (SvgaInfoRec.depth != 15 && SvgaInfoRec.depth != 16) {
                kprintf("\nError: Invalid weight specified for bpp 16: %d%d%d\n", \
                    xf86weight.red, xf86weight.green, xf86weight.blue);
                return FALSE;
            }
        }
        else
#endif
        {
            SvgaInfoRec.depth = 16;
            xf86weight.red = 5;
            xf86weight.green = 6;
            xf86weight.blue = 5;
        }
        break;
    case 24:
        SvgaInfoRec.depth = 24;
        SvgaInfoRec.bitsPerPixel = 24;
        if (!defaultVisualGiven)
            SvgaInfoRec.defaultVisual = TrueColor;
        xf86weight.red = 8;
        xf86weight.green = 8;
        xf86weight.blue = 8;
        break;
    case 32:
        SvgaInfoRec.depth = 24;
        SvgaInfoRec.bitsPerPixel = 32;
        if (!defaultVisualGiven)
            SvgaInfoRec.defaultVisual = TrueColor;
        xf86weight.red = 8;
        xf86weight.green = 8;
        xf86weight.blue = 8;
        break;

#endif
#endif
    default:
        kprintf("\nError: Unsupported bpp \"%i\"\n", xf86bpp);
        return FALSE;
    }

    vgaBitsPerPixel = SvgaInfoRec.bitsPerPixel;
    vgaBytesPerPixel = SvgaInfoRec.bitsPerPixel >> 3;

    if (defaultColorVisualClass < 0)
        defaultColorVisualClass = SvgaInfoRec.defaultVisual;

    switch (SvgaInfoRec.depth) {
    case 1:
        if (defaultColorVisualClass != StaticGray) {
            kprintf("\nError: Visual \"%s\" isn't supported at depth %d\n", \
	               xf86VisualNames[defaultColorVisualClass], SvgaInfoRec.depth);
        return FALSE;
    }
    case 4:
    switch (defaultColorVisualClass) {
    case StaticGray:
    case GrayScale:
    case StaticColor:
    case PseudoColor:
      break; /* these are OK */
    default:
        kprintf("\nError: Visual \"%s\" isn't supported at depth %d\n", \
	            xf86VisualNames[defaultColorVisualClass], SvgaInfoRec.depth);
      return FALSE;
    }
    break;

    case 8:
        break; /* all visuals supported at 8bpp */

    default:
        if (defaultColorVisualClass != TrueColor) {
            kprintf("\nError: Visual \"%s\" isn't supported at depth %d\n", \
                xf86VisualNames[defaultColorVisualClass], SvgaInfoRec.depth);
            return FALSE;
        }
    }

    /* First do a general PCI probe (unless disabled) */
    if (!OFLG_ISSET(OPTION_NO_PCI_PROBE, &SvgaInfoRec.options)) {
        vgaPCIInfo =  xf86scanpci(0);
    }

    for (i=0; Drivers[i]; i++) {
        if ((Drivers[i]->ChipProbe)()) {
            vgaSaveScreenFunc = Drivers[i]->ChipSaveScreen;
            xf86ProbeFailed = FALSE;

#ifdef MONOVGA
#ifdef BANKEDMONOVGA
            /*
             * In the mono mode we use, the memory is divided into 4 planes
             * so we can only effectively use 1/4 of the total.  For cards
             * with < 256K there should be fewer planes.
             */
            if (SvgaInfoRec.videoRam <= 256 || !SvgaInfoRec.bankedMono) {
                needmem = Drivers[i]->ChipSegmentSize * 8;
            }
            else {
                needmem = SvgaInfoRec.videoRam / 4 * 1024 * 8;
            }
#else /* BANKEDMONOVGA */
            needmem = Drivers[i]->ChipSegmentSize * 8;
#endif /* BANKEDMONOVGA */
            rounding = 32;
#else /* MONOVGA */
#ifdef XF86VGA16
            needmem = SvgaInfoRec.videoRam / 4 * 1024 * 8;
            rounding = 32;
#else
            needmem = SvgaInfoRec.videoRam * 1024;
            rounding = Drivers[i]->ChipRounding;
            /*
             * Correct 'needmem' for 16/32bpp.
             * For 8/16/32bpp, needmem is defined as the max. number of pixels.
             */
            needmem /= (vgaBitsPerPixel / 8);

#endif /* XF86VGA16 */
#endif /* MONOVGA */

            if (xf86Verbose) {
                kprintf("%s %s: chipset:  %s\n", \
                    OFLG_ISSET(XCONFIG_CHIPSET,&SvgaInfoRec.xconfigFlag) ? \
                    XCONFIG_GIVEN : XCONFIG_PROBED, \
                    SvgaInfoRec.name, SvgaInfoRec.chipset);

#ifdef MONOVGA
                kprintf("%s %s: videoram: %dk (using %dk)", \
#else
#ifdef XF86VGA16
                kprintf("%s %s: videoram: %dk (using %dk)", \
#else
                kprintf("%s %s: videoram: %dk", \
#endif
#endif
               OFLG_ISSET(XCONFIG_VIDEORAM,&SvgaInfoRec.xconfigFlag) ? \
                XCONFIG_GIVEN : XCONFIG_PROBED, \
                SvgaInfoRec.name, SvgaInfoRec.videoRam, \
#ifdef MONOVGA
                needmem / 8 / 1024);
#endif
#ifdef XF86VGA16
                needmem / 2 / 1024);
#endif

                for (j=0; j < SvgaInfoRec.clocks; j++) {
                    if ((j % 8) == 0)
                        kprintf("\n%s %s: clocks:", \
                            OFLG_ISSET(XCONFIG_CLOCKS,&SvgaInfoRec.xconfigFlag)? \
                            XCONFIG_GIVEN : XCONFIG_PROBED, SvgaInfoRec.name);
//                    kprintf(" %6.2f", (double)SvgaInfoRec.clock[j]/1000.0);
                }
                kprintf("\n");
            }

            /* Scale raw clocks to give pixel clocks if driver requires it */
            if ((Drivers[i]->ChipClockMulFactor > 1)
                || (Drivers[i]->ChipClockDivFactor > 1)) {
                for (j = 0; j < SvgaInfoRec.clocks; j++) {
                    SvgaInfoRec.clock[j] *= Drivers[i]->ChipClockDivFactor;
                    SvgaInfoRec.clock[j] /= Drivers[i]->ChipClockMulFactor;
                }
                SvgaInfoRec.maxClock *= Drivers[i]->ChipClockDivFactor;
                SvgaInfoRec.maxClock /= Drivers[i]->ChipClockMulFactor;

                if (xf86Verbose) {
                    kprintf("%s %s: Effective pixel clocks available:\n", \
                               XCONFIG_PROBED, SvgaInfoRec.name);

                    for (j=0; j < SvgaInfoRec.clocks; j++) {
                        if ((j % 8) == 0) {
                            if (j != 0)
                                kprintf("\n");
                            kprintf("%s %s: pixel clocks:", XCONFIG_PROBED, \
                                SvgaInfoRec.name);
                        }
//                        kprintf(" %6.2f", (double)SvgaInfoRec.clock[j] / 1000.0);
                    }
                    kprintf("\n");
                }
            }

            /*
            * If bpp is > 8, make sure the driver supports it.
            */
#if !defined(MONOVGA) && !defined(XF86VGA16)
            if ((vgaBitsPerPixel == 16 && !Drivers[i]->ChipHas16bpp)
                || (vgaBitsPerPixel == 24 && !Drivers[i]->ChipHas24bpp)
                || (vgaBitsPerPixel == 32 && !Drivers[i]->ChipHas32bpp)) {
                kprintf("\n%s %s: %dbpp not supported for this chipset\n", \
                    XCONFIG_GIVEN, SvgaInfoRec.name, vgaBitsPerPixel);
                Drivers[i]->ChipEnterLeave(LEAVE);
                return(FALSE);
            }
#endif
            vgaEnterLeaveFunc = Drivers[i]->ChipEnterLeave;
            vgaInitFunc = Drivers[i]->ChipInit;
            vgaValidModeFunc = Drivers[i]->ChipValidMode;
            vgaSaveFunc = Drivers[i]->ChipSave;
            vgaRestoreFunc = Drivers[i]->ChipRestore;
            vgaAdjustFunc = Drivers[i]->ChipAdjust;
            vgaFbInitFunc = Drivers[i]->ChipFbInit;

            vgaSetReadFunc = Drivers[i]->ChipSetRead;
            vgaSetWriteFunc = Drivers[i]->ChipSetWrite;
            vgaSetReadWriteFunc = Drivers[i]->ChipSetReadWrite;

            vgaMapSize = Drivers[i]->ChipMapSize;
            vgaSegmentSize = Drivers[i]->ChipSegmentSize;
            vgaSegmentShift = Drivers[i]->ChipSegmentShift;
            vgaSegmentMask = Drivers[i]->ChipSegmentMask;
            vgaReadBottom =
                         (pointer)((unsigned long)Drivers[i]->ChipReadBottom);
            vgaReadTop = (pointer)((unsigned long)Drivers[i]->ChipReadTop);
            vgaWriteBottom =
                         (pointer)((unsigned long)Drivers[i]->ChipWriteBottom);
            vgaWriteTop = (pointer)((unsigned long)Drivers[i]->ChipWriteTop);
            vgaUse2Banks = Drivers[i]->ChipUse2Banks;
            vgaInterlaceType = Drivers[i]->ChipInterlaceType;
            vgaOptionFlags = Drivers[i]->ChipOptionFlags;
            OFLG_SET(OPTION_POWER_SAVER, &vgaOptionFlags);
            OFLG_SET(OPTION_CLGD6225_LCD, &vgaOptionFlags);
            OFLG_SET(OPTION_NO_PCI_PROBE, &vgaOptionFlags);
            OFLG_SET(OPTION_CLKDIV2, &vgaOptionFlags);
            /* For XAA */
            OFLG_SET(OPTION_XAA_BENCHMARK, &vgaOptionFlags);
            OFLG_SET(OPTION_XAA_NO_COL_EXP, &vgaOptionFlags);
            OFLG_SET(OPTION_NO_PIXMAP_CACHE, &vgaOptionFlags);

            xf86VerifyOptions(&vgaOptionFlags, &SvgaInfoRec);

            /* We do this after the option has been verified. */
#if !defined(MONOVGA) && !defined(XF86VGA16)
            if (vgaBitsPerPixel == 8
                && OFLG_ISSET(OPTION_DAC_8_BIT, &SvgaInfoRec.options)) {
                kprintf("%s %s: Using 8 bits per color component\n", \
                    XCONFIG_GIVEN, SvgaInfoRec.name);
                DAC8Bit = TRUE;
                xf86weight.red = xf86weight.green = xf86weight.blue = 8;
            }
            SvgaInfoRec.blackColour.red = 0;
            SvgaInfoRec.blackColour.green = 0;
            SvgaInfoRec.blackColour.blue = 0;

            SvgaInfoRec.weight.red = xf86weight.red;
            SvgaInfoRec.weight.green = xf86weight.green;
            SvgaInfoRec.weight.blue = xf86weight.blue;

            SvgaInfoRec.whiteColour.red =  (0x0001 << xf86weight.red) - 1;
            SvgaInfoRec.whiteColour.green = (0x0001 << xf86weight.green) - 1;
            SvgaInfoRec.whiteColour.blue = (0x0001 << xf86weight.blue) - 1;

            kprintf("%s %s: Using %d bpp, Depth %d, Color weight: %d%d%d\n", \
                XCONFIG_GIVEN, SvgaInfoRec.name, vgaBitsPerPixel,
                SvgaInfoRec.depth, SvgaInfoRec.weight.red,
                SvgaInfoRec.weight.green, SvgaInfoRec.weight.blue);
#endif

            if (OFLG_ISSET(OPTION_CLGD6225_LCD, &SvgaInfoRec.options))
                clgd6225Lcd = TRUE;

	/* if Virtual given: is the virtual size too big? */
#ifdef BANKEDMONOVGA
	if (SvgaInfoRec.virtualX > (2048)) {
 		kprintf("%s: Virtual width %i exceeds max. virtual width %i\n", \
		       SvgaInfoRec.name, SvgaInfoRec.virtualX, (2048));
		vgaEnterLeaveFunc(LEAVE);
		return(FALSE);
	}
	SvgaInfoRec.displayWidth = ((SvgaInfoRec.virtualX + rounding - 1) /
		rounding) * rounding;
	if (SvgaInfoRec.displayWidth*SvgaInfoRec.virtualY <= 8*vgaSegmentSize)
	{	/* may be unbanked */
		if (SvgaInfoRec.displayWidth > SvgaInfoRec.virtualX)
			kprintf("%s %s: Display width set to %d (a multiple of" \
			       " %d)\n", XCONFIG_PROBED, SvgaInfoRec.name, \
			       SvgaInfoRec.displayWidth, rounding);
	}
	else if (SvgaInfoRec.virtualX > (1024))
		SvgaInfoRec.displayWidth=2048;
	     else SvgaInfoRec.displayWidth=1024;

	if (SvgaInfoRec.virtualX > 0 &&
	    SvgaInfoRec.displayWidth * SvgaInfoRec.virtualY > needmem)
	  {
	    kprintf("%s: Too little memory for virtual resolution\n" \
                   "      %d (display width %d) x %d\n", \
                   SvgaInfoRec.name, SvgaInfoRec.virtualX, \
                   SvgaInfoRec.displayWidth, SvgaInfoRec.virtualY);
            vgaEnterLeaveFunc(LEAVE);
	    return(FALSE);
	  }
#else
#ifndef USE_OLD_ROUNDING
            if (SvgaInfoRec.virtualX > 0) {
            /* Let the driver have a chance to use a larger screen pitch if
             * it needs.  This ability is particularly useful for the Cirrus
             * Laguna family, which uses tiled memory.  Each scanline must be
             * an integer number of tiles wide, where tiles are 128 or 256
             * bytes wide.  Furthermore, there are only a few tile pitches
             * allowed.  It just so happens that none of these tile pitches
             * yield a screen byte pitch that is divisible by 3.  The upshot:
             * you can't have 24bpp if the screen pitch is not a multiple of
             * three -- i.e., if the screen pitch is not an integer number
             *   of _pixels_.
             */
                if (vgaPitchAdjustFunc != (int (*)())NoopDDA) {
                    SvgaInfoRec.displayWidth = (*vgaPitchAdjustFunc)();
                }
                else {
                    if (SvgaInfoRec.virtualX % rounding) {
                        SvgaInfoRec.displayWidth = SvgaInfoRec.virtualX +
                            (rounding -(SvgaInfoRec.virtualX % rounding));
                        kprintf("%s %s: Display width set to %d (a multiple of" \
                            "%d)\n", XCONFIG_PROBED, SvgaInfoRec.name, \
                            SvgaInfoRec.displayWidth, rounding);
                    }
                    else {
                        SvgaInfoRec.displayWidth = SvgaInfoRec.virtualX;
                    }
                }

                if (SvgaInfoRec.displayWidth * SvgaInfoRec.virtualY > needmem) {
                    kprintf("%s: Too little memory for virtual resolution " \
                            "%d %d\n", SvgaInfoRec.name, SvgaInfoRec.virtualX, \
                        SvgaInfoRec.virtualY);
                    vgaEnterLeaveFunc(LEAVE);
                    return(FALSE);
                }
            }
#else
            if (SvgaInfoRec.virtualX > 0 &&
                SvgaInfoRec.virtualX * SvgaInfoRec.virtualY > needmem) {
                kprintf("%s: Too little memory for virtual resolution %d %d\n", \
                    SvgaInfoRec.name, SvgaInfoRec.virtualX, \
                    SvgaInfoRec.virtualY);
                vgaEnterLeaveFunc(LEAVE);
                return(FALSE);
            }
#endif
#endif

            maxX = maxY = -1;
            tx = SvgaInfoRec.virtualX;
            ty = SvgaInfoRec.virtualY;

            if (Drivers[i]->ChipBuiltinModes) {
                pEnd = pMode = SvgaInfoRec.modes = Drivers[i]->ChipBuiltinModes;
                kprintf("%s %s: Using builtin driver modes\n", \
                        XCONFIG_PROBED, SvgaInfoRec.name);
                do {
                    kprintf("%s %s: Builtin Mode: %s\n", \
                            XCONFIG_PROBED, SvgaInfoRec.name, pMode->name);
                    if (pMode->HDisplay > maxX) {
                        maxX = pMode->HDisplay;
                        pmaxX = pMode;
                    }

                    if (pMode->VDisplay > maxY) {
                        maxY = pMode->VDisplay;
                        pmaxY = pMode;
                    }
                    pMode = pMode->next;
                } while (pMode != pEnd);
            }
            else if (SvgaInfoRec.modes == NULL) {
                kprintf("No modes supplied in XF86Config\n");
                vgaEnterLeaveFunc(LEAVE);
                return(FALSE);
            }
            else {
                pMode = SvgaInfoRec.modes;
                pEnd = (DisplayModePtr) NULL;
                do {
                    DisplayModePtr pModeSv;

                    /*
                    * xf86LookupMode returns FALSE if it ran into an invalid
                    * parameter
                    */
                    if(xf86LookupMode(pMode, &SvgaInfoRec, LOOKUP_DEFAULT)
                        == FALSE) {
                        pModeSv = pMode->next;
                        xf86DeleteMode(&SvgaInfoRec, pMode);
                        pMode = pModeSv;
                    }
                    else if (pMode->HDisplay * pMode->VDisplay > needmem) {
                        pModeSv=pMode->next;
                        kprintf("%s %s: Insufficient video memory for all " \
                               "resolutions\n", XCONFIG_PROBED, \
                               SvgaInfoRec.name);
                        xf86DeleteMode(&SvgaInfoRec, pMode);
                        pMode = pModeSv;
                    }
                    else if (((tx > 0) && (pMode->HDisplay > tx)) ||
                        ((ty > 0) && (pMode->VDisplay > ty))) {
                        pModeSv=pMode->next;
                        kprintf("%s %s: Resolution %dx%d too large for " \
                               "virtual %dx%d\n", XCONFIG_PROBED, \
                                SvgaInfoRec.name, \
                                pMode->HDisplay, pMode->VDisplay, tx, ty);
                        xf86DeleteMode(&SvgaInfoRec, pMode);
                        pMode = pModeSv;
                    }
                    else {
                       /*
                         * Successfully looked up this mode.  If pEnd isn't
                         * initialized, set it to this mode.
                         */
                        if (pEnd == (DisplayModePtr) NULL)
                            pEnd = pMode;

                        if (pMode->HDisplay > maxX)
                        {
                            maxX = pMode->HDisplay;
                            pmaxX = pMode;
                        }
                        if (pMode->VDisplay > maxY)
                        {
                            maxY = pMode->VDisplay;
                            pmaxY = pMode;
                        }

                        pMode = pMode->next;
                    }
                } while (pMode != pEnd);
            }

            SvgaInfoRec.virtualX = max(maxX, SvgaInfoRec.virtualX);
            SvgaInfoRec.virtualY = max(maxY, SvgaInfoRec.virtualY);

#ifdef BANKEDMONOVGA
	if (SvgaInfoRec.virtualX > (2048)) {
		kprintf("%s: Max. width %i exceeds max. virtual width %i\n", \
			SvgaInfoRec.name, SvgaInfoRec.virtualX, (2048));
		vgaEnterLeaveFunc(LEAVE);
		return(FALSE);
	}
	/* Now that modes are resolved and max. extents are found,
	 * test size again */
	SvgaInfoRec.displayWidth = ((SvgaInfoRec.virtualX + rounding - 1) /
		rounding) * rounding;
	if (SvgaInfoRec.displayWidth*SvgaInfoRec.virtualY > 8*vgaSegmentSize)
	  {
             if (SvgaInfoRec.virtualX > (1024))
		SvgaInfoRec.displayWidth=2048;
	     else SvgaInfoRec.displayWidth=1024;
          }
	if ((xf86Verbose) &&
	    (SvgaInfoRec.displayWidth != SvgaInfoRec.virtualX))
		kprintf("%s %s: Display width set to %d (a multiple of %d)\n", \
			XCONFIG_PROBED, SvgaInfoRec.name, SvgaInfoRec.displayWidth, \
			rounding);
#endif

#ifndef BANKEDMONOVGA
#ifndef USE_OLD_ROUNDING
            if (SvgaInfoRec.displayWidth < 0) {
            /* Let the driver have a chance to use a larger screen pitch if
             * it needs.  This ability is particularly useful for the Cirrus
             * Laguna family, which uses tiled memory.  Each scanline must be
             * an integer number of tiles wide, where tiles are 128 or 256
             * bytes wide.  Furthermore, there are only a few tile pitches
             * allowed.  It just so happens that none of these tile pitches
             * yield a screen byte pitch that is divisible by 3.  The upshot:
             * you can't have 24bpp if the screen pitch is not a multiple of
             * three -- i.e., if the screen pitch is not an integer number
             * of _pixels_.
             */
                if (vgaPitchAdjustFunc != (int (*)())NoopDDA) {
                    SvgaInfoRec.displayWidth = (*vgaPitchAdjustFunc)();
                }
                else {
                    if (SvgaInfoRec.virtualX % rounding) {
                        SvgaInfoRec.displayWidth =  SvgaInfoRec.virtualX +
                                (rounding - (SvgaInfoRec.virtualX % rounding));
                        kprintf("%s %s: Display width set to %d " \
                               "(a multiple of %d)\n", \
                               XCONFIG_PROBED, SvgaInfoRec.name, \
                               SvgaInfoRec.displayWidth, rounding);
                    }
                    else {
                        SvgaInfoRec.displayWidth = SvgaInfoRec.virtualX;
                    }
                }
                if (SvgaInfoRec.displayWidth * SvgaInfoRec.virtualY > needmem) {
                    kprintf("%s: Too little memory for virtual resolution " \
                           "%d %d\n", SvgaInfoRec.name, SvgaInfoRec.virtualX, \
                            SvgaInfoRec.virtualY);
                    vgaEnterLeaveFunc(LEAVE);
                    return(FALSE);
                }
            }
#else
            if (SvgaInfoRec.virtualX % rounding) {
                SvgaInfoRec.virtualX -= SvgaInfoRec.virtualX % rounding;
                kprintf("%s %s: Virtual width rounded down to a multiple of " \
                       "%d (%d)\n", XCONFIG_PROBED, SvgaInfoRec.name, \
                       rounding, SvgaInfoRec.virtualX);
                if (SvgaInfoRec.virtualX < maxX) {
                    kprintf("%s: Rounded down virtual width (%d) " \
                           "is too small for mode %s", SvgaInfoRec.name, \
                           SvgaInfoRec.virtualX, pmaxX->name);
                    vgaEnterLeaveFunc(LEAVE);
                    return(FALSE);
                }
            }

            if ( SvgaInfoRec.virtualX * SvgaInfoRec.virtualY > needmem) {
                if (SvgaInfoRec.virtualX != maxX ||
                     SvgaInfoRec.virtualY != maxY) {
                    kprintf("%s: Too little memory to accomodate virtual " \
                           "size and mode %s\n", SvgaInfoRec.name, \
                           (SvgaInfoRec.virtualX == maxX) ? \
                           pmaxX->name : pmaxY->name);
                }
                else {
                    kprintf("%s: Too little memory to accomodate modes %s " \
                           "and %s\n", SvgaInfoRec.name, pmaxX->name, \
                           pmaxY->name);
                    vgaEnterLeaveFunc(LEAVE);
                }
                return(FALSE);
            }
#endif
#else
	if ( SvgaInfoRec.displayWidth * SvgaInfoRec.virtualY > needmem) {
		kprintf("%s: Too little memory to accomodate display width %i" \
			" and virtual height %i\n", \
			SvgaInfoRec.name, \
			SvgaInfoRec.displayWidth, SvgaInfoRec.virtualY);
		vgaEnterLeaveFunc(LEAVE);
		return(FALSE);
	}
#endif

            if ((tx != SvgaInfoRec.virtualX) || (ty != SvgaInfoRec.virtualY)) {
                OFLG_CLR(XCONFIG_VIRTUAL,&SvgaInfoRec.xconfigFlag);
            }

#ifdef USE_OLD_ROUNDING
#ifndef BANKEDMONOVGA
                /* Let the driver have a chance to use a larger screen pitch if
                it needs.  This ability is particularly useful for the Cirrus
                Laguna family, which uses tiled memory.  Each scanline must be
                an integer number of tiles wide, where tiles are 128 or 256
                bytes wide.  Furthermore, there are only a few tile pitches
                allowed.  It just so happens that none of these tile pitches
                yield a screen byte pitch that is divisible by 3.  The upshot:
                you can't have 24bpp if the screen pitch is not a multiple of
                three -- i.e., if the screen pitch is not an integer number
            of _pixels_. */

            if (vgaPitchAdjustFunc != (int (*)())NoopDDA) {
                SvgaInfoRec.displayWidth = (*vgaPitchAdjustFunc)();
            }
            else {
                SvgaInfoRec.displayWidth = SvgaInfoRec.virtualX;
            }
#endif
#endif
            if (xf86Verbose) {
                kprintf("%s %s: Virtual resolution set to %dx%d\n", \
                       OFLG_ISSET(XCONFIG_VIRTUAL,&SvgaInfoRec.xconfigFlag) ? \
                       XCONFIG_GIVEN : XCONFIG_PROBED, SvgaInfoRec.name, \
                       SvgaInfoRec.virtualX, SvgaInfoRec.virtualY);
            }

#if !defined(XF86VGA16)
#if !defined(MONOVGA)
	if ((SvgaInfoRec.speedup & ~SPEEDUP_ANYWIDTH) &&
            SvgaInfoRec.displayWidth != 1024)
	  {
	    kprintf("%s %s: SpeedUp code selection modified because " \
	            "virtualX != 1024\n", \
                XCONFIG_PROBED, SvgaInfoRec.name);
	    SvgaInfoRec.speedup &= SPEEDUP_ANYWIDTH;
	    OFLG_CLR(XCONFIG_SPEEDUP,&SvgaInfoRec.xconfigFlag);
	  }

        /*
         * Currently the 16bpp and 32bpp modes use stock cfb with linear
         * addressing, so avoid the SpeedUp code for these depths.
         */
      if (vgaBitsPerPixel == 8) {

        useSpeedUp = SvgaInfoRec.speedup & SPEEDUP_ANYCHIPSET;
        if (useSpeedUp && xf86Verbose)
          kprintf("%s %s: Generic SpeedUps selected (Flags=0x%x)\n", \
               OFLG_ISSET(XCONFIG_SPEEDUP,&SvgaInfoRec.xconfigFlag) ? \
               XCONFIG_GIVEN : XCONFIG_PROBED, SvgaInfoRec.name, useSpeedUp);
      } /* endif vgaBitsPerPixel == 8 */

	/* Initialise chip-specific enhanced fb functions */
	(*vgaFbInitFunc)();

	/* The driver should now have determined whether linear */
	/* addressing is possible */
	vgaUseLinearAddressing = Drivers[i]->ChipUseLinearAddressing;
	vgaPhysLinearBase = Drivers[i]->ChipLinearBase;
	vgaLinearSize = Drivers[i]->ChipLinearSize;

#ifdef XFreeXDGA
	if (SvgaInfoRec.directMode & XF86DGADirectPresent)
	    SvgaInfoRec.directMode |= XF86DGAAccelPresent;
	if (vgaUseLinearAddressing) {
	    SvgaInfoRec.physBase = vgaPhysLinearBase;
	    SvgaInfoRec.physSize = SvgaInfoRec.videoRam * 1024;
	} else {
	    SvgaInfoRec.physBase = 0xA0000 + Drivers[i]->ChipWriteBottom;
	    SvgaInfoRec.physSize = Drivers[i]->ChipSegmentSize;
	    SvgaInfoRec.setBank = vgaSetVidPage;
	}
#endif

	/* Currently linear addressing is required for 16/32bpp. */
	/* Bail out if it is not enabled. */
	if (vgaBitsPerPixel > 8 && !vgaUseLinearAddressing) {
 	    kprintf("%s: Linear addressing is required for %dbpp\n", \
     	    SvgaInfoRec.name, vgaBitsPerPixel);
	    vgaEnterLeaveFunc(LEAVE);
	    return(FALSE);
	}

#else
#ifdef BANKEDMONOVGA
	if (vgaUse2Banks)
	{
	  ourmfbDoBitbltCopy = mfbDoBitbltTwoBanksCopy;
	  ourmfbDoBitbltCopyInverted = mfbDoBitbltTwoBanksCopyInverted;
	}
	else
	{
	  ourmfbDoBitbltCopy = mfbDoBitbltCopy;
	  ourmfbDoBitbltCopyInverted = mfbDoBitbltCopyInverted;
	}
#else
	ourmfbDoBitbltCopy = mfbDoBitbltTwoBanksCopy;
	ourmfbDoBitbltCopyInverted = mfbDoBitbltTwoBanksCopyInverted;
#endif /* BANKEDMONOVGA */
#endif /* !MONOVGA */
#endif /* !XF86VGA16 */

	if (!OFLG_ISSET(OPTION_NO_PCI_PROBE, &SvgaInfoRec.options)) {
	  /* Free PCI information */
	  xf86cleanpci();
	}

	return TRUE;
     }
  }


  vgaSaveScreenFunc = vgaHWSaveScreen;

  /* Free PCI information */
  xf86cleanpci();

  if (SvgaInfoRec.chipset) {
      kprintf("%s: '%s' is an invalid chipset", SvgaInfoRec.name, \
                 SvgaInfoRec.chipset);
  }

  return FALSE;
}


/* Allow each driver to optionally set a display pitch other than the
(default) virtualX size.  This functionality was added by Corin
Anderson while he was bringing up support for 24bpp and the Laguna
family of Cirrus Logic chips. */
void vgaSetPitchAdjustHook(int (* ChipPitchAdjust)())
{
    vgaPitchAdjustFunc = ChipPitchAdjust;
}


/* Allow each driver to optionally set an offset of the
frame buffer data from the linear base address. */
void vgaSetLinearOffsetHook(int (* ChipLinearOffset)())
{
    vgaLinearOffsetFunc = ChipLinearOffset;
}


/* Allow each driver to hook the ScreenInit function */
void vgaSetScreenInitHook(Boolean (* ChipScrInit)())
{
//	vgaScrInitFunc = (Boolean(*)())ChipScrInit;
	vgaScrInitFunc = (Boolean(*)(ScreenPtr, char *, int, int, int, int, int))ChipScrInit;
}

int Set_LogicalWidth(DisplayModePtr mode)
{
      SvgaInfoRec.virtualX = mode->HDisplay;
      SvgaInfoRec.displayWidth = mode->HDisplay;
      SvgaInfoRec.virtualY = mode->VDisplay;

      return 0;
 }

/*
  * vgaScreenInit --
  *      Attempt to find and initialize a VGA framebuffer
  *      Most of the elements of the ScreenRec are filled in.  The
  *      video is enabled for the frame buffer...
  */
Boolean
vgaScreenInit(int scr_index,ScreenPtr pScreen, int argc,char **argv)
{
    int displayResolution = 75;    /* default to 75dpi */
    extern int monitorResolution;
    DisplayModePtr mode = (DisplayModePtr) argv[0];

    if (serverGeneration == 1) {
        vgaBase = xf86MapVidMem(scr_index, VGA_REGION,
                               (pointer)0xA0000,  vgaMapSize);

        if (vgaUseLinearAddressing) {
            vgaLinearBase = xf86MapVidMem(scr_index, LINEAR_REGION,
                  (pointer) ((unsigned long)vgaPhysLinearBase), vgaLinearSize);

            vgaLinearOrig = vgaLinearBase; /* save copy of original base */
        }

#ifdef MONOVGA
    if (SvgaInfoRec.displayWidth * SvgaInfoRec.virtualY >= vgaSegmentSize * 8) {
        kprintf("%s %s: Using banked mono vga mode\n", \
                XCONFIG_PROBED, SvgaInfoRec.name);
        vgaVirtBase = (pointer)VGABASE;
    }
    else {
      kprintf("%s %s: Using non-banked mono vga mode\n", \
          XCONFIG_PROBED, SvgaInfoRec.name);
      vgaVirtBase = vgaBase;
    }
#else
#ifndef XF86VGA16
    vgaVirtBase = (pointer)vgaBase;
#else
    vgaVirtBase = (pointer)vgaBase; //(pointer)VGABASE;
#endif
#endif

        /* This doesn't mean anything yet for SVGA 16/32bpp (no banking). */
        if (vgaUseLinearAddressing) {
            if (vgaLinearOffsetFunc != (int (*)())NoopDDA)
                vgaLinearBase = (void *)((unsigned long)vgaLinearBase
                + (*vgaLinearOffsetFunc)());
            vgaReadBottom = vgaLinearBase;
            vgaReadTop = (void *)((unsigned int)vgaLinearSize
                + (unsigned long)vgaLinearBase);
            vgaWriteBottom = vgaLinearBase;
            vgaWriteTop = (void *)((unsigned int)vgaLinearSize
                + (unsigned long)vgaLinearBase);
            vgaSegmentSize = vgaLinearSize;    /* override */
            vgaSegmentMask = vgaLinearSize - 1;
            vgaSetReadFunc = (void (*)())NoopDDA;
            vgaSetWriteFunc = (void (*)())NoopDDA;
            vgaSetReadWriteFunc = (void (*)())NoopDDA;
        }
        else {
            vgaReadBottom  = (void *)((unsigned long)vgaReadBottom
                + (unsigned long)vgaBase);
            vgaReadTop     = (void *)((unsigned long)vgaReadTop
                + (unsigned long)vgaBase);
            vgaWriteBottom = (void *)((unsigned long)vgaWriteBottom
                + (unsigned long)vgaBase);
            vgaWriteTop    = (void *)((unsigned long)vgaWriteTop
                + (unsigned long)vgaBase);
        }
    }

   if (!(*vgaInitFunc)(mode)) {
        kprintf("%s: hardware initialisation failed\n", SvgaInfoRec.name);
        DebugBreak();
    }

    /*
     * This function gets called while in graphics mode during a server
     * reset, and this causes the original video state to be corrupted.
     * So,only initialise vgaOrigVideoState if it hasn't previously been done
     * DHD Dec 1991.
     */
    if (!vgaOrigVideoState) {
        vgaOrigVideoState = (pointer)(*vgaSaveFunc)(vgaOrigVideoState);
    }

    (*vgaRestoreFunc)(vgaNewVideoState);

#ifndef DIRTY_STARTUP
    vgaSaveScreen(NULL, FALSE); /* blank the screen */
#endif
    (*vgaAdjustFunc)(SvgaInfoRec.frameX0, SvgaInfoRec.frameY0);

    /*
     * Take display resolution from the -dpi flag if specified
     */

    if (monitorResolution) {
        displayResolution = monitorResolution;
    }

    /*
     * Inititalize the dragon to color display
     */
#if 0
#ifndef XF86VGA16
#ifdef MONOVGA
  if (!mfbScreenInit(pScreen,
		     (pointer) vgaVirtBase,
		     SvgaInfoRec.virtualX,
		     SvgaInfoRec.virtualY,
		     displayResolution, displayResolution,
		     SvgaInfoRec.displayWidth))
#else
    xf86AccelInfoRec.ServerInfoRec = &SvgaInfoRec;
    if (vgaBitsPerPixel == 8) {
        if (!xf86XAAScreenInitvga256(pScreen,
            (pointer) vgaVirtBase,
            SvgaInfoRec.virtualX,
            SvgaInfoRec.virtualY,
            displayResolution, displayResolution,
            SvgaInfoRec.displayWidth)) {
            return(FALSE);
        }
    }
    if (vgaBitsPerPixel == 16) {
        if (!xf86XAAScreenInit16bpp(pScreen,
            vgaLinearBase,
            SvgaInfoRec.virtualX,
            SvgaInfoRec.virtualY,
            displayResolution, displayResolution,
            SvgaInfoRec.displayWidth)) {
            return(FALSE);
        }
    }
    if (vgaBitsPerPixel == 24) {
        if (!xf86XAAScreenInit24bpp(pScreen,
            vgaLinearBase,
            SvgaInfoRec.virtualX,
            SvgaInfoRec.virtualY,
            displayResolution, displayResolution,
            SvgaInfoRec.displayWidth)) {
            return(FALSE);
        }
    }
    if (vgaBitsPerPixel == 32) {
        if (!xf86XAAScreenInit32bpp(pScreen,
            vgaLinearBase,
            SvgaInfoRec.virtualX,
            SvgaInfoRec.virtualY,
            displayResolution, displayResolution,
            SvgaInfoRec.displayWidth)) {

            return(FALSE);
        }
    }
#endif
#else /* XF86VGA16 */
  Init16Output(pScreen,
		     (pointer) vgaVirtBase,
		     SvgaInfoRec.virtualX,
		     SvgaInfoRec.virtualY,
		     displayResolution, displayResolution,
		     SvgaInfoRec.displayWidth);
#endif /* XF86VGA16 */
#endif

    pScreen->whitePixel = 1;
    pScreen->blackPixel = 0;
    XF86FLIP_PIXELS();

    /* For 16/32bpp, the cfb defaults are OK. */
#ifndef MONOVGA
    if (vgaBitsPerPixel <= 8) { /* For 8bpp SVGA and VGA16 */
#if 0
        pScreen->InstallColormap = vgaInstallColormap;
        pScreen->UninstallColormap = vgaUninstallColormap;
        pScreen->ListInstalledColormaps = vgaListInstalledColormaps;
        pScreen->StoreColors = vgaStoreColors;
#endif
    }

    /* Let each chip driver have a whack at hooking functions, etc. */
    if (!(*vgaScrInitFunc)(pScreen,  (char*)vgaLinearBase, SvgaInfoRec.virtualX,
        SvgaInfoRec.virtualY, displayResolution, displayResolution,
        SvgaInfoRec.displayWidth)) {
        return FALSE;
    }
#endif

    pScreen->CloseScreen = vgaCloseScreen;
#ifndef DIRTY_STARTUP
    /* Fill the screen with black */
    if (serverGeneration == 1) {
        pointer    vgaVirtPtr;
#if defined(MONOVGA) || defined(XF86VGA16)
        pointer    vgaPhysPtr;
#endif
#if !defined(BANKEDMONOVGA)
        if (vgaUseLinearAddressing) {
            /* use original linear base from MapVidMem() */
            kprintf("vgaLinearOrig = %x\n", vgaLinearOrig);
            memset(vgaLinearOrig, pScreen->blackPixel,
                SvgaInfoRec.videoRam * 1024);
        }
        else /* banked: */
#endif
            for (vgaVirtPtr = vgaVirtBase;
#if defined(MONOVGA) || defined(XF86VGA16)
           vgaVirtPtr<(pointer)((char *)vgaVirtBase+(SvgaInfoRec.videoRam*256));
#else
            vgaVirtPtr<(pointer)((char *)vgaVirtBase+(SvgaInfoRec.videoRam*1024));
#endif
            vgaVirtPtr = (pointer)((char *)vgaVirtPtr + vgaSegmentSize)){
#if defined(MONOVGA)
	        if (vgaVirtBase == vgaBase) {
                /* Not using banking mode */
                vgaPhysPtr = vgaBase;
            }
            else
#endif

#if defined(XF86VGA16)
            {
                /* Set the bank, then clear it */
                vgaPhysPtr=  vgaVirtPtr;//NULL;//vgaSetWrite(vgaVirtPtr);
            }
            memset(vgaPhysPtr,pScreen->blackPixel,vgaSegmentSize);
#endif
        }
    }
#if defined(XF86VGA16)
    vgaLinearBase = vgaVirtBase;
#endif

    vgaSaveScreen(NULL, TRUE); /* unblank the screen */
#endif /* ! DIRTY_STARTUP */

    savepScreen = pScreen;

    return(TRUE);
}

static void saveDummy() {}

/*
 * vgaEnterLeaveVT --
 *      grab/ungrab the current VT completely.
 */

void
vgaEnterLeaveVT(Boolean enter,int screen_idx)
{
//    ScreenPtr   pScreen = savepScreen;

    if (enter) {
        vgaInitFunc = saveInitFunc;
        vgaSaveFunc = saveSaveFunc;
        vgaRestoreFunc = saveRestoreFunc;
        vgaAdjustFunc = saveAdjustFunc;
        vgaSaveScreenFunc = saveSaveScreenFunc;
        vgaSetReadFunc = saveSetReadFunc;
        vgaSetWriteFunc = saveSetWriteFunc;
        vgaSetReadWriteFunc = saveSetReadWriteFunc;

        xf86MapDisplay(screen_idx, VGA_REGION);
        if (vgaUseLinearAddressing) {
            xf86MapDisplay(screen_idx, LINEAR_REGION);
        }

        (*vgaEnterLeaveFunc)(ENTER);

        vgaOrigVideoState = (pointer)(*vgaSaveFunc)(vgaOrigVideoState);
        (*vgaRestoreFunc)(vgaNewVideoState);
    }
    else {
        /* Make sure that another driver hasn't disabeled IO */
        xf86MapDisplay(screen_idx, VGA_REGION);
        if (vgaUseLinearAddressing) {
            xf86MapDisplay(screen_idx, LINEAR_REGION);
        }
        (*vgaEnterLeaveFunc)(ENTER);

        /*
         * We come here in many cases,but one is special: When the server aborts
         * abnormaly. Therefore there MUST be a check whether vgaOrigVideoState
         * is valid or not.
         */
        {
            if (vgaOrigVideoState)
                (*vgaRestoreFunc)(vgaOrigVideoState);

            (*vgaEnterLeaveFunc)(LEAVE);

            xf86UnMapDisplay(screen_idx, VGA_REGION);
            if (vgaUseLinearAddressing)
            {
                xf86UnMapDisplay(screen_idx, LINEAR_REGION);
            }
        }

        saveInitFunc = vgaInitFunc;
        saveSaveFunc = vgaSaveFunc;
        saveRestoreFunc = vgaRestoreFunc;
        saveAdjustFunc = vgaAdjustFunc;
        saveSaveScreenFunc = vgaSaveScreenFunc;
        saveSetReadFunc = vgaSetReadFunc;
        saveSetWriteFunc = vgaSetWriteFunc;
        saveSetReadWriteFunc = vgaSetReadWriteFunc;

        vgaInitFunc = (Boolean (*)(DisplayModePtr))saveDummy;
        vgaSaveFunc = (void * (*)(void *))saveDummy;
        vgaRestoreFunc = (void (*)(void *))saveDummy;
        vgaAdjustFunc = (void (*)(int, int))saveDummy;
        vgaSetReadFunc = (void (*)())saveDummy;
        vgaSetWriteFunc = (void (*)())saveDummy;
        vgaSetReadWriteFunc = (void (*)())saveDummy;
        vgaSaveScreenFunc = (void (*)(long))saveDummy;
    }
}

/*
 * vgaCloseScreen --
 *      called to ensure video is enabled when server exits.
 */
Boolean
  vgaCloseScreen(int  screen_idx, ScreenPtr pScreen)
{
    /*
      * Hmm... The server may shut down even if it is not running on the
      * current vt. Let's catch this casehere.
      */
    xf86Exiting = TRUE;

    if (xf86VTSema)
        vgaEnterLeaveVT(LEAVE, screen_idx);

    return(TRUE);
}

/*
 * vgaAdjustFrame --
 *      Set a new viewport
 */
void
vgaAdjustFrame(int x, int  y)
{
    (*vgaAdjustFunc)(x, y);
}

/*
 * vgaSwitchMode --
 *     Set a new display mode
 */
Boolean
vgaSwitchMode(DisplayModePtr mode)
{
    if ((*vgaInitFunc)(mode)) {
        (*vgaRestoreFunc)(vgaNewVideoState);
            return(TRUE);
    }
    else {
        kprintf("Mode switch failed because of hardware initialisation error\n");
        return(FALSE);
    }
}

/*
 * vgaValidMode --
 *     Validate a mode for VGA architecture. Also checks the chip driver
 *     to see if the mode can be supported.
 */
int
vgaValidMode(DisplayModePtr mode,Boolean verbose,int flag)
{
    return (*vgaValidModeFunc)(mode, verbose, flag);
}
